package com.geor.gcv.core.model;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.nutz.json.Json;
import org.nutz.lang.Mirror;
import org.slf4j.Logger;

import com.geor.common.log.Loggers;

public class ParamValue {
	protected static Logger log = Loggers.get();

	private static final int CASE_INT = 0;
	private static final int CASE_DOUBLE = 1;
	private static final int CASE_STRING = 2;
	private static final int CASE_LIST = 3;
	private static final int CASE_MAP = 4;
	private static final int CASE_BOOLEAN = 5;
	private static final int CASE_BOOL = 6;

	public static final String TYPE_BLOCKSIZES = "blockSizes";
	public static final String TYPE_CONSTVALUES = "constValues";
	public static final String TYPE_MIN = "min";
	public static final String TYPE_MAX = "max";
	public static final String TYPE_TIMES = "times";
	public static final String TYPE_PRECENT = "percentage";
	public static final String TYPE_BLOCKSIZE = "blockSize";
	public static final String TYPE_CONSTVAL = "constVal";
	public static final String TYPE_CANNYVAL = "cannyVal";
	public static final String TYPE_DEBUG = "debug";
	public static final String TYPE_IMSHOW = "imshow";

	public static Set<String> types = new HashSet<String>();
	public static Map<String, Integer> cases = new HashMap<String, Integer>();

	static {
		Mirror<ParamValue> mirror = Mirror.me(ParamValue.class);
		for (Field field : ParamValue.class.getDeclaredFields()) {
			if (field.getName().startsWith("TYPE_")) {
				types.add(mirror.getValue(null, field).toString());
			}
			if (field.getName().startsWith("CASE_")) {
				field.setAccessible(true);
				try {
					cases.put(field.getName().split("_")[1].toLowerCase(), field.getInt(null));
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private String name;

	private Object value;

	public ParamValue(String key) {
		if (!key.startsWith(":") && key.contains(":")) {
			ParamValue tmp = convert(key);
			this.name = tmp.name;
			this.value = tmp.value;
		} else {
			toException(String.format("[%s]数据格式错误!", key));
		}
	}

	protected void toException(String mess) {
		throw new IllegalArgumentException(mess);
	}

	private ParamValue convert(String key) {
		// 得到类型
		String type = null;
		if (key.indexOf('(') != -1) {
			type = key.substring(key.indexOf('(') + 1, key.length() - 1);
			key = key.substring(0, key.indexOf("("));
		}

		// 得到名称
		String name = key.substring(0, key.indexOf(':'));
		if (null == name || !types.contains(name)) {
			toException(String.format("不存在该声明[%s],在[paramValue]中!", name));
		}

		// 得到值
		String value = key.substring(key.indexOf(':') + 1, key.length());

		// 判断类型
		int mark = -1;
		if (type != null) {
			if (cases.get(type.toLowerCase().substring(0,
					type.toLowerCase().indexOf("<") == -1 ? type.length() : type.toLowerCase().indexOf("<"))) == null) {
				toException(String.format("不存在该类型[%s],在[paramValue]中!", type));
			}
			mark = cases.get(type.toLowerCase().substring(0,
					type.toLowerCase().indexOf("<") == -1 ? type.length() : type.toLowerCase().indexOf("<")));
		} else {
			mark = CASE_STRING;
		}
		try {
			switch (mark) {
			case CASE_INT:
				return new ParamValue(name, Integer.parseInt(value));
			case CASE_DOUBLE:
				return new ParamValue(name, Double.parseDouble(value));
			case CASE_STRING:
				return new ParamValue(name, value);
			case CASE_LIST:
				if (type.indexOf('<') == -1 || type.indexOf('>') == -1) {
					return new ParamValue(name, Json.fromJsonAsList(String.class, value));
				}

				String tmp = type.substring(type.indexOf('<') + 1, type.lastIndexOf('>'));
				int flag = -1;
				if (cases.get(tmp) != null) {
					flag = cases.get(tmp);
				}
				System.out.println(flag);
				switch (flag) {
				case CASE_INT:
					return new ParamValue(name, Json.fromJsonAsList(Integer.class, value));
				case CASE_DOUBLE:
					return new ParamValue(name, Json.fromJsonAsList(Double.class, value));
				case CASE_BOOL:
					return new ParamValue(name, Json.fromJsonAsList(Boolean.class, value));
				case CASE_BOOLEAN:
					return new ParamValue(name, Json.fromJsonAsList(Boolean.class, value));
				default:
					toException(String.format("[%s]该类型没有定义", tmp));
				}

			case CASE_MAP:
				log.warn("map类型转换还没实现!");
				break;
			case CASE_BOOL:
				if ("true".equals(value) || "false".equals(value)) {
					return new ParamValue(name, Boolean.parseBoolean(value));
				}
				toException("");
			case CASE_BOOLEAN:
				if ("true".equals(value) || "false".equals(value)) {
					return new ParamValue(name, Boolean.parseBoolean(value));
				}
				toException("");
			}
		} catch (Exception e) {
			e.printStackTrace();
			switch (mark) {
			case CASE_INT:
				toException(String.format("[%s]不能转为int类型", value));
			case CASE_DOUBLE:
				toException(String.format("[%s]不能转为double类型", value));
			case CASE_LIST:
				toException(String.format("[%s]不能转为list类型", value));
			case CASE_BOOL:
				toException(String.format("[%s]不能转为boolean类型", value));
			case CASE_BOOLEAN:
				toException(String.format("[%s]不能转为boolean类型", value));
			}
			return null;
		}
		return new ParamValue(name, value);
	}

	public ParamValue(String name, Object val) {
		setName(name);
		setValue(val);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Object getValue() {
		return value;
	}

	public void setValue(Object value) {
		this.value = value;
	}

	@Override
	public String toString() {
		return String.format("{%s:%s}", name, Json.toJson(value));
	}

}
